package view;

import java.awt.BorderLayout;
import java.awt.Event;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.List;

import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JDesktopPane;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;

import options.view.ViewSettings;
import snmpstatistics.StatisticsPanel;
import alarm.RemoveAlarmPanel;
import alarm.SendAlarmPanel;
import capture.Captor;
import capture.CapturePanel;
import capture.PacketAnalyzerLoader;
import capture.analyzer.AbstractPacketAnalyzer;
import controller.FrameWorkListener;
import features.SNMPClient;
import features.SNMPException;
import features.SNMPSession;

public class FrameWork extends JFrame {

	private static final long serialVersionUID = 497158696253896552L;
	private FrameWorkListener listener = null;
	private JPanel jContentPane = null;
	private JMenuBar jMyMenuBar = null;
	private JMenu fileMenu = null;
	private JMenu editMenu = null;
	private JMenu helpMenu = null;
	private JMenuItem exitMenuItem = null;
	private JMenuItem aboutMenuItem = null;
	private JMenuItem cutMenuItem = null;
	private JMenuItem copyMenuItem = null;
	private JMenuItem pasteMenuItem = null;
	private JMenuItem saveMenuItem = null;
	private JMenu toolMenu = null;
	private JMenuItem optionsMenuItem = null;
	private JDesktopPane jDesktopMainPane = null;
	private JToolBar jToolBar = null;
	private JButton buttonShutDown = null;
	private JButton buttonDiscovery = null;	
	private MainFrame mainFrame = null;
	private JButton buttonStatistics = null;
	private JButton buttonStartCapture = null;	
	private JButton buttonStopCapture = null;	
	private JButton buttonSettings = null;	
	private JButton buttonAlarms = null;	
	private JButton buttonNoAlarms = null;
	private JToolBar jStatusBar;
	private static JTextField txtStatus = null;

	private Captor captor;
	private CapturePanel capturePanel;
	private JLabel statusLabel;
	private JMenu viewMenu;
	private JMenu datalinkMenu;
	private JMenu networkMenu;
	private JMenu transportMenu;
	private JMenu applicationMenu;
	private JMenu[] tableViewMenu = null;
	private List<AbstractPacketAnalyzer> analyzers;

	/**
	 * This is the default constructor
	 */
	public FrameWork() {
		super();
		PacketAnalyzerLoader.loadDefaultAnalyzer();
		analyzers = (List<AbstractPacketAnalyzer>) PacketAnalyzerLoader.getAnalyzers();
		initialize();
		listener = new FrameWorkListener(this);
	}

	public CapturePanel getCapturePanel(){
		if(capturePanel==null){
			captor = new Captor(this);
			capturePanel = new CapturePanel(captor);
			loadProperty();
		}
		return capturePanel;
	}

	/**
	 * This method initializes jMenu	
	 * 	
	 * @return javax.swing.JMenu	
	 */
	private JMenu getToolMenu() {
		if (toolMenu == null) {
			toolMenu = new JMenu();
			toolMenu.setText("Strumenti");
			toolMenu.add(getOptionsMenuItem());
		}
		return toolMenu;
	}

	/**
	 * This method initializes jMenuItem	
	 * 	
	 * @return javax.swing.JMenuItem	
	 */
	public JMenuItem getOptionsMenuItem() {
		if (optionsMenuItem == null) {
			optionsMenuItem = new JMenuItem();
			optionsMenuItem.setText("Opzioni");
		}
		return optionsMenuItem;
	}

	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		ViewSettings.getSettings().setIcon(this);
		ViewSettings.getSettings().setLookAndFeel(this);
		this.setJMenuBar(getJMyMenuBar());

		this.setExtendedState(JFrame.MAXIMIZED_BOTH);
		this.setContentPane(getJContentPane());
		this.setTitle("Monitor SNMP");
		this.setSize(new java.awt.Dimension(522,203));
		this.setVisible(true);
		this.setEnabled(true);
	}

	public JLabel getStatusLabel() {
		if (statusLabel == null) {
			statusLabel = new JLabel("In avvio...");
		}

		return statusLabel;
	}

	/**
	 * This method initializes jContentPane
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(new BorderLayout());
			jContentPane.add(getJToolBar(), java.awt.BorderLayout.NORTH);
			jContentPane.add(getStatusLabel(), java.awt.BorderLayout.SOUTH);
			jContentPane.add(getJDesktopMainPane(), java.awt.BorderLayout.CENTER);
			setDesktopPanel(getCapturePanel());
		}
		return jContentPane;
	}

	public void setDesktopPanel(JPanel panel) {
		if(panel==null)
			panel = getCapturePanel();
		getJDesktopMainPane().removeAll();
		getJDesktopMainPane().add(panel);
		getJDesktopMainPane().validate();

	}

	/**
	 * This method initializes jJMenuBar	
	 * 	
	 * @return javax.swing.JMenuBar	
	 */
	private JMenuBar getJMyMenuBar() {
		if (jMyMenuBar == null) {
			jMyMenuBar = new JMenuBar();
			jMyMenuBar.add(getFileMenu());
			jMyMenuBar.add(getEditMenu());
			jMyMenuBar.add(getViewMenu());
//			jMyMenuBar.add(getToolMenu());
			jMyMenuBar.add(getHelpMenu());
		}
		return jMyMenuBar;
	}

	public JMenu[] getView(){
		if (tableViewMenu == null) {
			tableViewMenu = new JMenu[4];
			tableViewMenu[0] = getDatalinkMenu();
			tableViewMenu[1] = getNetworkMenu();
			tableViewMenu[2] = getTransportMenu();
			tableViewMenu[3] = getApplicationMenu();
			JMenu item;
			JMenuItem subitem;
			for(int i=0;i<analyzers.size();i++){
				AbstractPacketAnalyzer analyzer = analyzers.get(i);
				item = new JMenu(analyzer.getProtocolName());
				String[] valueNames = analyzer.getValueNames();
				if(valueNames == null) 
					continue;
				for(int j=0;j<valueNames.length;j++){
					subitem = new JCheckBoxMenuItem(valueNames[j]);
					subitem.setActionCommand("TableView"+i);
					subitem.addActionListener(new ActionListener(){
						public void actionPerformed(ActionEvent evt){
							String cmd = evt.getActionCommand();
							if(cmd.startsWith("TableView")){
								int index = Integer.parseInt(cmd.substring(9));
								JCheckBoxMenuItem item = (JCheckBoxMenuItem)evt.getSource();
								capturePanel.getTable().setTableView(analyzers.get(index),item.getText(),item.isSelected());
							}
						};							
					});
					item.add(subitem);
				}
				tableViewMenu[analyzer.layer].add(item);
			}
		}
		return tableViewMenu;
	}


	/**
	 * This method initializes jMenu	
	 * 	
	 * @return javax.swing.JMenu	
	 */
	private JMenu getViewMenu() {
		if (viewMenu == null) {
			viewMenu = new JMenu();
			viewMenu.setText("Info Pacchetti");
			viewMenu.add(getView()[0]);
			viewMenu.add(getView()[1]);
			viewMenu.add(getView()[2]);
			viewMenu.add(getView()[3]);
		}
		return viewMenu;
	}

	/**
	 * This method initializes jMenu	
	 * 	
	 * @return javax.swing.JMenu	
	 */
	private JMenu getDatalinkMenu() {
		if (datalinkMenu == null) {
			datalinkMenu = new JMenu();
			datalinkMenu.setText("Datalink Layer");
		}
		return datalinkMenu;
	}

	/**
	 * This method initializes jMenu	
	 * 	
	 * @return javax.swing.JMenu	
	 */
	private JMenu getNetworkMenu() {
		if (networkMenu == null) {
			networkMenu = new JMenu();
			networkMenu.setText("Network Layer");
		}
		return networkMenu;
	}

	/**
	 * This method initializes jMenu	
	 * 	
	 * @return javax.swing.JMenu	
	 */
	private JMenu getTransportMenu() {
		if (transportMenu == null) {
			transportMenu = new JMenu();
			transportMenu.setText("Transport Layer");
		}
		return transportMenu;
	}

	/**
	 * This method initializes jMenu	
	 * 	
	 * @return javax.swing.JMenu	
	 */
	private JMenu getApplicationMenu() {
		if (applicationMenu == null) {
			applicationMenu = new JMenu();
			applicationMenu.setText("Application Layer");
		}
		return applicationMenu;
	}

	/**
	 * This method initializes jMenu	
	 * 	
	 * @return javax.swing.JMenu	
	 */
	private JMenu getFileMenu() {
		if (fileMenu == null) {
			fileMenu = new JMenu();
			fileMenu.setText("File");
			fileMenu.add(getSaveMenuItem());
			fileMenu.add(getExitMenuItem());
		}
		return fileMenu;
	}

	/**
	 * This method initializes jMenu	
	 * 	
	 * @return javax.swing.JMenu	
	 */
	private JMenu getEditMenu() {
		if (editMenu == null) {
			editMenu = new JMenu();
			editMenu.setText("Modifica");
			editMenu.add(getCutMenuItem());
			editMenu.add(getCopyMenuItem());
			editMenu.add(getPasteMenuItem());
		}
		return editMenu;
	}

	/**
	 * This method initializes jMenu	
	 * 	
	 * @return javax.swing.JMenu	
	 */
	private JMenu getHelpMenu() {
		if (helpMenu == null) {
			helpMenu = new JMenu();
			helpMenu.setText("Guida");
			helpMenu.add(getAboutMenuItem());
		}
		return helpMenu;
	}

	/**
	 * This method initializes jMenuItem	
	 * 	
	 * @return javax.swing.JMenuItem	
	 */
	public JMenuItem getExitMenuItem() {
		if (exitMenuItem == null) {
			exitMenuItem = new JMenuItem();
			exitMenuItem.setText("Esci");
		}
		return exitMenuItem;
	}

	/**
	 * This method initializes jMenuItem	
	 * 	
	 * @return javax.swing.JMenuItem	
	 */
	public JMenuItem getAboutMenuItem() {
		if (aboutMenuItem == null) {
			aboutMenuItem = new JMenuItem();
			aboutMenuItem.setText("Informazioni su...");
		}
		return aboutMenuItem;
	}

	/**
	 * This method initializes jMenuItem	
	 * 	
	 * @return javax.swing.JMenuItem	
	 */
	private JMenuItem getCutMenuItem() {
		if (cutMenuItem == null) {
			cutMenuItem = new JMenuItem();
			cutMenuItem.setText("Taglia");
			cutMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, Event.CTRL_MASK, true));
		}
		return cutMenuItem;
	}

	/**
	 * This method initializes jMenuItem	
	 * 	
	 * @return javax.swing.JMenuItem	
	 */
	private JMenuItem getCopyMenuItem() {
		if (copyMenuItem == null) {
			copyMenuItem = new JMenuItem();
			copyMenuItem.setText("Copia");
			copyMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, Event.CTRL_MASK, true));
		}
		return copyMenuItem;
	}

	/**
	 * This method initializes jMenuItem	
	 * 	
	 * @return javax.swing.JMenuItem	
	 */
	private JMenuItem getPasteMenuItem() {
		if (pasteMenuItem == null) {
			pasteMenuItem = new JMenuItem();
			pasteMenuItem.setText("Incolla");
			pasteMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, Event.CTRL_MASK, true));
		}
		return pasteMenuItem;
	}

	/**
	 * This method initializes jMenuItem	
	 * 	
	 * @return javax.swing.JMenuItem	
	 */
	private JMenuItem getSaveMenuItem() {
		if (saveMenuItem == null) {
			saveMenuItem = new JMenuItem();
			saveMenuItem.setText("Salva");
			saveMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, Event.CTRL_MASK, true));
		}
		return saveMenuItem;
	}

	//sembra inutile
	/**
	 * This method initializes jDesktopPane	
	 * 	
	 * @return javax.swing.JDesktopPane	
	 */
	public JDesktopPane getJDesktopMainPane() {
		if (jDesktopMainPane == null) {
			jDesktopMainPane = new JDesktopPane();
			jDesktopMainPane.setBackground(java.awt.SystemColor.controlDkShadow);
			jDesktopMainPane.setLayout(new BoxLayout(jDesktopMainPane, BoxLayout.X_AXIS));
		}
		return jDesktopMainPane;
	}

	/**
	 * This method initializes jJToolBarBar	
	 * 	
	 * @return javax.swing.JToolBar	
	 */
	public JToolBar getJToolBar() {
		if (jToolBar == null) {
			jToolBar = new JToolBar();
			jToolBar.setName("Barra degli strumenti");

			jToolBar.add(getButtonShutDown());
			jToolBar.addSeparator();
			jToolBar.add(getButtonMapping());
			jToolBar.addSeparator();
			jToolBar.add(getButtonStartCapture());
			jToolBar.add(getButtonStopCapture());
			jToolBar.addSeparator();
			jToolBar.add(getButtonAlarms());
			jToolBar.add(getButtonNoAlarms());
			jToolBar.addSeparator();
			jToolBar.add(getButtonStatistics());
//			jToolBar.addSeparator();
//			jToolBar.add(getButtonSettings());

			jToolBar.setFloatable(false);
		}
		return jToolBar;
	}

	//sembra inutile
	public JToolBar getJStatusBar() {
		if (jStatusBar == null) {
			jStatusBar = new JToolBar();
			jStatusBar.setName("Barra di stato");

			JPanel p = new JPanel(new BorderLayout());
			p.setSize(this.getWidth(), 25);
			p.setBorder(javax.swing.BorderFactory.createEtchedBorder(javax.swing.border.EtchedBorder.RAISED));
			p.add(getTxtStatus(), null);
			jStatusBar.add(p, null);

			jStatusBar.setFloatable(false);
		}
		return jStatusBar;
	}

	public JTextField getTxtStatus(){
		if(txtStatus == null) { 
			txtStatus = new JTextField();
			txtStatus.setEditable(false);
			txtStatus.setBorder(null);
		}
		return txtStatus;
	}

	/**
	 * This method initializes buttonLogIn	
	 * 	
	 * @return javax.swing.JButton	
	 */
	public JButton getButtonShutDown() {
		if (buttonShutDown == null) {
			buttonShutDown = new JButton();
			buttonShutDown.setIcon(new ImageIcon("images/Shut_Down.png"));
		}
		return buttonShutDown;
	}

	/**
	 * This method initializes jButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	public JButton getButtonMapping() {
		if (buttonDiscovery == null) {
			buttonDiscovery = new JButton();
			buttonDiscovery.setIcon(new ImageIcon("images/Discovery.png"));
			buttonDiscovery.setToolTipText("Network Discovery");
		}
		return buttonDiscovery;
	}

	public void appendMainFrame(){
		if(mainFrame == null){
			mainFrame = new MainFrame(this);

			getJDesktopMainPane().add(mainFrame);

			mainFrame.setVisible(true);
		}
	}

	/**
	 * This method initializes jButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	public JButton getButtonStatistics() {
		if (buttonStatistics == null) {
			buttonStatistics = new JButton();
			buttonStatistics.setIcon(new ImageIcon("images/Statistics.png"));
			buttonStatistics.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					try {
						SNMPSession session = SNMPClient.startSession(SNMPClient.VERSION_2C);
						session.init(SNMPClient.DEFAULT_IP, SNMPClient.DEFAULT_PORT_STRING, SNMPClient.DEFAULT_COMMUNITY);
						
						JDialog dialog = new JDialog(FrameWork.this, "Statistiche: " );
						dialog.setSize(new java.awt.Dimension(470, 460));
						dialog.setResizable(false);
						ViewSettings.getSettings().centerDialog(dialog);
						
						JPanel panel = new StatisticsPanel(FrameWork.this);
						dialog.add(panel);
						dialog.setVisible(true);
					} catch (SNMPException e1) {
						e1.printStackTrace();
					}
				}
			});
		}
		return buttonStatistics;
	}

	/**
	 * This method initializes jButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	public JButton getButtonAlarms() {
		if (buttonAlarms == null) {
			buttonAlarms = new JButton();
			buttonAlarms.setIcon(new ImageIcon("images/Alarms.png"));
			buttonAlarms.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					JDialog dialog = new JDialog(FrameWork.this, "Nuovo alarm");
					dialog.setSize(505, 300);
					ViewSettings.getSettings().centerDialog(dialog);
					JPanel panel = new SendAlarmPanel();
					dialog.add(panel);
					dialog.addWindowListener(new WindowAdapter() {
						@Override
						public void windowOpened(WindowEvent e) {
							super.windowOpened(e);
							getButtonAlarms().setEnabled(false);
							getButtonNoAlarms().setEnabled(false);
						}

						@Override
						public void windowDeactivated(WindowEvent e) {
							super.windowDeactivated(e);

							getButtonAlarms().setEnabled(true);
							getButtonNoAlarms().setEnabled(true);
						}
					});
					dialog.setVisible(true);
				}
			});
		}
		return buttonAlarms;
	}

	/**
	 * This method initializes jButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	public JButton getButtonNoAlarms() {
		if (buttonNoAlarms == null) {
			buttonNoAlarms = new JButton();
			buttonNoAlarms.setIcon(new ImageIcon("images/NoAlarms.png"));
			buttonNoAlarms.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					JDialog dialog = new JDialog(FrameWork.this, "Rimozione alarm");
					dialog.setSize(510, 310);
					ViewSettings.getSettings().centerDialog(dialog);
					JPanel panel = new RemoveAlarmPanel();
					dialog.add(panel);
					dialog.addWindowListener(new WindowAdapter() {
						@Override
						public void windowOpened(WindowEvent e) {
							super.windowOpened(e);
							getButtonAlarms().setEnabled(false);
							getButtonNoAlarms().setEnabled(false);
						}
						@Override
						public void windowDeactivated(WindowEvent e) {
							super.windowDeactivated(e);
							getButtonAlarms().setEnabled(true);
							getButtonNoAlarms().setEnabled(true);
						}
					});

					dialog.setVisible(true);
				}
			});
		}
		return buttonNoAlarms;
	}

	/**
	 * This method initializes jButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	public JButton getButtonStartCapture() {
		if (buttonStartCapture == null) {
			buttonStartCapture = new JButton();
			buttonStartCapture.setIcon(new ImageIcon("images/StartCapture.png"));
		}
		return buttonStartCapture;
	}

	/**
	 * This method initializes jButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	public JButton getButtonStopCapture() {
		if (buttonStopCapture == null) {
			buttonStopCapture = new JButton();
			buttonStopCapture.setIcon(new ImageIcon("images/StopCapture.png"));
			buttonStopCapture.setEnabled(false);
		}
		return buttonStopCapture;
	}

	/**
	 * This method initializes jButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	public JButton getButtonSettings() {
		if (buttonSettings == null) {
			buttonSettings = new JButton();
			buttonSettings.setIcon(new ImageIcon("images/Settings.png"));
			buttonSettings.setText("Impostazioni");
			buttonSettings.setToolTipText("Impostazioni");
		}
		return buttonSettings;
	}

	/**
	 */
	public MainFrame getMainFrame(){
		return mainFrame;
	}

	/**
	 */
	public FrameWorkListener getListener(){
		return listener;
	}

	public void reset() {
		if(this.mainFrame != null)
			this.mainFrame.setVisible(false);
		this.mainFrame = null;
	}

	public static void sendMessage(String msg) {
		FrameWork.sendMessage(msg, "OK", JOptionPane.INFORMATION_MESSAGE);
	}

	public static void sendMessage(String msg, String title, int messageType) {
		if(txtStatus != null) {
			new Thread(new Runnable() {
				public void run() {
					try {
						Thread.sleep(4000);
						txtStatus.setText("");
					} catch (InterruptedException exc) {}
				}
			}).start();

			txtStatus.setText(msg);
		}
		JOptionPane.showMessageDialog(null, msg, title, messageType);
	}

	public void startUpdating(){
		JDFrameUpdater.setRepeats(true);
		JDFrameUpdater.start();
	}

	public void stopUpdating(){
		JDFrameUpdater.stop();
		JDFrameUpdater.setRepeats(false);
		JDFrameUpdater.start();
	}

	javax.swing.Timer JDFrameUpdater=new javax.swing.Timer(500,new ActionListener(){
		public void actionPerformed(ActionEvent evt){
			capturePanel.fireTableChanged();
			getStatusLabel().setText("Catturati "+captor.getPackets().size()+" pacchetti.");
			repaint();
		}
	});

	public Captor getCaptor() {
		return captor;
	}

	public void setCaptor(Captor captor) {
		this.captor = captor;
	}

	public List<AbstractPacketAnalyzer> getAnalyzers() {
		return analyzers;
	}

	public void setAnalyzers(List<AbstractPacketAnalyzer> analyzers) {
		this.analyzers = analyzers;
	}

	public void loadProperty(){
		setSize(Integer.parseInt(Captor.preferences.get("WinWidth","640")),
				Integer.parseInt(Captor.preferences.get("WinHeight","480")));
		setLocation(Integer.parseInt(Captor.preferences.get("WinX","0")),
				Integer.parseInt(Captor.preferences.get("WinY","0")));
	}

	public void saveProperty(){
		Captor.preferences.put("WinWidth",String.valueOf(getBounds().width));
		Captor.preferences.put("WinHeight",String.valueOf(getBounds().height));
		Captor.preferences.put("WinX",String.valueOf(getBounds().x));
		Captor.preferences.put("WinY",String.valueOf(getBounds().y));

		capturePanel.saveProperty();

		Captor.saveProperty();
	}

	public void enableCapture(){
		getButtonStartCapture().setEnabled(true);
		getButtonStopCapture().setEnabled(false);
		getButtonMapping().setEnabled(true);
	}

	public void disableCapture(){
		getButtonStartCapture().setEnabled(false);
		getButtonStopCapture().setEnabled(true);
		getButtonMapping().setEnabled(false);
	}
}
